package java_0305_heap_leetcode;

import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;

/**
 * 找出数组中最小的k个数。以任意顺序返回这k个数均可
 * 取小数用大堆
 * 0 <= len(arr) <= 100000
 * 0 <= k <= min(100000, len(arr))
 */
public class Num17_14_SmallestK {
    public int[] smallestK(int[] arr, int k) {
        //边界条件
        if(arr.length==0||k==0){
            return new int[0];
        }
        //构造一个最大堆（JDK内部是默认是最小堆，要使用比较器改造为最大堆）
        //要把最小堆改为最大堆，就是要告诉编译器值越大，让编译器看来它反而小
        Queue<Integer> queue=new PriorityQueue<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });
        //扫描原数组集合，优先级队列中只存储k个值
        for (int i :arr) {
            if(queue.size()<k){
                queue.offer(i);
            }else{
                //当前扫描元素和堆顶元素的关系
                //若扫描元素>堆顶元素，它就大于堆中所有元素值，这个值一定不是要找的值
                int peek= queue.peek();//获取堆顶元素值
                if(i>peek){
                    continue;//此元素不符合进行下一个循环判断下一个元素
                }else{
                    //此时当前元素<堆顶元素，将堆顶元素出队，将较小值入队
                    queue.poll();
                    queue.offer(i);
                }
            }
        }
        //此时扫描完集合，最大堆中就保存了最小的k个数，出队即可
        int[] ret=new int[k];
        for (int i = 0; i < k; i++) {
            ret[i]=queue.poll();
        }
        return ret;
    }
}
